// wifi_manager.c
#include "wifi_manager.h"
#include <string.h>

#define TAG "WiFiManage"

#define MAX_EVENT_CBS 5

static wifi_manager_event_cb_t event_cbs[MAX_EVENT_CBS] = {0};
static void *event_user_ctxs[MAX_EVENT_CBS] = {0};

static DeviceConfig manager;

static int retry_count = 0;
static const int max_retry = 5;


esp_err_t wifi_manager_register_event_cb(wifi_manager_event_cb_t cb, void* user_ctx) {
    for (int i = 0; i < MAX_EVENT_CBS; i++) {
        if (event_cbs[i] == NULL) {
            event_cbs[i] = cb;
            event_user_ctxs[i] = user_ctx;
            return ESP_OK;
        }
    }
    return ESP_ERR_NO_MEM;
}

void wifi_manager_trigger_event(wifi_manager_event_t event) {
    for (int i = 0; i < MAX_EVENT_CBS; i++) {
        if (event_cbs[i] != NULL) {
            event_cbs[i](event, event_user_ctxs[i]);
        }
    }
}

void wifi_event_handler(void *event_handler_arg, esp_event_base_t event_base,
						int32_t event_id, void *event_data) {
	// 设备作为AP时，STA连接事件
	if (event_id == WIFI_EVENT_AP_STACONNECTED) {
		wifi_event_ap_staconnected_t *event =
			(wifi_event_ap_staconnected_t *)event_data;
		ESP_LOGI(TAG, "station  %s join, AID=%d", event->mac, event->aid);
		retry_count = 0;
		// 设备作为AP时，STA断开事件
	} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
		wifi_event_ap_stadisconnected_t *event =
			(wifi_event_ap_stadisconnected_t *)event_data;
		ESP_LOGI(TAG, "station %s leave, AID=%d", event->mac, event->aid);
		// 设备作为STA连接到AP成功事件
	} else if (event_id == WIFI_EVENT_STA_CONNECTED) {
		wifi_event_sta_connected_t *event =
			(wifi_event_sta_connected_t *)event_data;
		ESP_LOGI(TAG, "sta_connected %s leave, AID=%d", event->ssid,
				 event->aid);
		wifi_manager_trigger_event(WIFI_EVENT_CONNECTED);
		retry_count = 0;
		// 设备作为STA断开AP事件
	} else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
		wifi_event_sta_disconnected_t *event =
			(wifi_event_sta_disconnected_t *)event_data;
		ESP_LOGI(TAG, "sta_disconnected %s leave, reason=%d", event->ssid,
				 event->reason);

		// 如果重试次数没超过最大重试次数，尝试重新连接
		if (retry_count < max_retry) {
			esp_wifi_connect();
			retry_count++;
			ESP_LOGI("WIFI", "Retrying to connect to the AP...");
		} else {
			ESP_LOGI("WIFI", "Failed to connect to the AP");
			wifi_manager_trigger_event(WIFI_EVENT_FAILED);
		}
	}
}

static void connect_to_wifi(char wifi_ssid[64], char wifi_pass[64]) {

	ESP_ERROR_CHECK(esp_netif_init());
	esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
	esp_netif_set_hostname(sta_netif, "BeixiangGateway");

	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
	ESP_ERROR_CHECK(esp_wifi_init(&cfg));

	wifi_config_t wifi_config = {};
	strncpy((char *)wifi_config.sta.ssid, wifi_ssid,
			sizeof(wifi_config.sta.ssid));
	strncpy((char *)wifi_config.sta.password, wifi_pass,
			sizeof(wifi_config.sta.password));

	esp_wifi_set_mode(WIFI_MODE_STA);
	esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
	esp_wifi_start();

	ESP_LOGI(TAG, "connect_to_wifi: ssid:%s pass:%s", manager.wifi_ssid,
			 manager.wifi_pass);

	ESP_ERROR_CHECK(esp_wifi_connect());
}

void wifi_manager_begin(void) {
	esp_err_t ret = nvs_flash_init();
	if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
		ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
		ESP_ERROR_CHECK(nvs_flash_erase()); // 清除NVS并重新初始化
		ESP_ERROR_CHECK(nvs_flash_init());
	}
	// 加载配置
	nvs_handle_t nvs;
	size_t len;
	esp_err_t err = nvs_open("storage", NVS_READONLY, &nvs);
	if (err == ESP_OK) {
		len = sizeof(manager.wifi_ssid);
		err = nvs_get_str(nvs, "ssid", manager.wifi_ssid, &len);
		if (err != ESP_OK || len == 0 || manager.wifi_ssid[0] == '\0') {
			ESP_LOGW(TAG, "SSID empty or not found");
			nvs_close(nvs);
			return; // SSID 不可用，直接返回不连接
		}

		len = sizeof(manager.wifi_pass);
		err = nvs_get_str(nvs, "pass", manager.wifi_pass, &len);
		if (err != ESP_OK) {
			// 密码读取失败可以视为无密码或空密码
			manager.wifi_pass[0] = '\0';
		}
		nvs_close(nvs);
	} else {
		ESP_LOGW(TAG, "Failed to open NVS storage");
		return;
	}
	connect_to_wifi(manager.wifi_ssid, manager.wifi_pass);

	ESP_ERROR_CHECK(esp_event_handler_instance_register(
		WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL));
}
